闲话 22.10.6
闲话
所以为什么模拟赛都喜欢考后缀题啊
前有一个SA 后有一个广义SAM上树剖
什么玩意 我只会非字符串的科技(
字符串能不能滚粗OIa
大渣好,我四渣渣辉,点一下,玩一年,装备不花一分钱,说话战斗,罩杯回收,找一基友,极限到手。
0 元 VIP,3 天满级,一秒一刀 999,装备全爆 666,广告做得再牛,不如进服遛一遛!
古天乐绿了,古天乐绿了,惊喜不断,月入上万!不花钱还赚钱的绿色游戏,等级能提现,装备换点钱!
我很奇怪lyin为什么在做核酸时念叨
然后lyin给我指了条明路
什么玩意
所以大家有什么很诡异的题吗 社论没题材了
[最近一直在唱yoasobi那首《怪物》 歌词待补]
杂题
Petya在收集美丽矩阵。一个 的美丽矩阵要保证:
- 所有的矩阵内的元素都是1~n的整数
- 每一行不能有相同的元素
- 每一对竖直相邻的元素不能相同。
Petya定义 稀有度 为将所有 的美丽矩阵按照字典序排好序(从0开始计数)该美丽矩阵所在的编号。他希望你求出他所给的矩阵的稀有度(模 998244353 )。
。
经典炒冷饭环节。
首先题意转化:
1+2:每行是一个 的排列
3:竖直可能需要广义错排
然后字典序一眼想到 Cantor 展开,但是 Cantor 也没说过矩阵怎么展开啊(
我们规定竖直方向是上面限制下面,这样第一排是没有限制的。我们可以通过 Cantor 展开来确定第一行的排名。现在拓展。
我们枚举 为字典序小于当前矩阵 的矩阵,直到 开始存在不同。
且 , 。然后本行剩下的数就能随便填了,本行以下的数也可以。本行内的数需要满足与上一行不相等,而本行以下的数就是一个。
我们发现本行内填法不是完全的错排,因为存在一部分数字没有在 中出现,且在 中出现了。记这部分数的数量为 ,它们使得这部分的答案是限制了 个位置错开的 ,记答案为 。
考虑 的生成。
当 是经典错排。
不妨设 ,且第 个位置没有限制。如果放 个有限制的数上去转移到 ,放 个没有限制的数上去转移到 。
于是有递推。
这个东西直接乘进去就行了。但是如果每次都扫一遍的话是 的。
考虑我们需要支持查询没有在 中出现且在 中出现的数字,支持给定 查询 的数字数量。使用 BIT 优化即可。
code
#include <bits/stdc++.h>
#define rep(i,a,b) for ( register int (i) = (a); (i) <= (b); ++(i) )
#define pre(i,a,b) for ( register int (i) = (a); (i) >= (b); --(i) )
using namespace std;
const int mod = 998244353, N = 2e3 + 10;
int n, t1, a[N][N], f[N][N], pw[N], tmp1[N], tmp2[N];
int ans, tot;
struct BIT{
int Index[N];
inline void add(int p, int v) {
if (p == 0) return;
for ( ; p <= n ; p += p & -p) Index[p] += v;
}
inline int qry(int p) {
int ret = 0;
for ( ; p ; p &= p-1) ret += Index[p];
return ret;
}
inline void clear() {
rep(i,1,n) Index[i] = 0;
}
} frt, bk;
typedef long long ll; typedef __int128 lll;
struct FastMod {
int m; ll b;
void init(int _m) { m = _m; b = ((lll)1<<64) / m; }
int operator () (ll a) {
ll q = ((lll) a * b) >> 64;
a -= q * m;
if (a >= m) a -= m;
return a;
}
} Mod;
int add(int a, int b) { return (a += b) >= mod ? a - mod : a; }
int mul(int a, int b) { return Mod(1ll * a * b); }
template<typename ...Args> int mul(int a, Args ...b) { return mul(a, mul(b...)); }
signed main() {
ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
cin >> n; pw[0] = 1; f[0][0] = 1; Mod.init(mod);
rep(i,1,n) rep(j,1,n) cin >> a[i][j];
rep(i,1,n) {
f[i][0] = mul(i, f[i-1][0]);
rep(j,1,i) {
if(i == j) f[i][i] = mul(i == 1 ? 0 : 1ll * (i-1), add(f[i-1][i-1], f[i-2][i-2]));
else f[i][j] = add(mul(j, f[i-1][j-1]), mul(i-j, f[i-1][j]));
}
}
rep(i,1,n) pw[i] = mul(pw[i-1], f[n][n]);
rep(i,1,n) {
int l = n;
rep(i,1,n) tmp1[i] = tmp2[i] = 0;
frt.clear(), bk.clear();
rep(i,1,n) bk.add(i, 1);
long long tmp = 0;
rep(j,1,n) {
if (tmp2[a[i-1][j]] == 0) {
l--; bk.add(a[i-1][j], -1);
}
tmp = add(tmp, mul(frt.qry(a[i][j] - 1), f[n - j][i > 1 ? l : 0]));
if (l != 0 or i == 1) tmp = add(tmp, mul(bk.qry(a[i][j]-1), f[n - j][i > 1 ? l - 1 : 0]));
tmp1[a[i][j]] == 0 ? bk.add(a[i][j], -1) : frt.add(a[i][j], -1);
tmp1[a[i-1][j]] = tmp2[a[i][j]] = 1;
if (tmp2[a[i-1][j]] == 0) frt.add(a[i-1][j], 1);
if (tmp1[a[i][j]] == 0) l--;
} ans = add(ans, mul(tmp, pw[n-i]));
} cout << ans;
}
以下是博客签名,与正文无关。
请按如下方式引用此页:
本文作者 joke3579,原文链接:https://www.cnblogs.com/joke3579/p/chitchat221006.html。
遵循 CC BY-NC-SA 4.0 协议。
请读者尽量不要在评论区发布与博客内文完全无关的评论,视情况可能删除。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)